www.gusucode.com > VC++写的C编译器源代码附设计文档-源码程序 > VC++写的C编译器源代码附设计文档-源码程序/code/C- Compiler/SymbolTable.cpp

    // SymbolTable.cpp : implementation file
// Download by http://www.NewXing.com

#include "stdafx.h"
#include "cminus.h"

#include "SymbolTable.h"

/*  *    CSymbolTable
    *    Construction & destruction
  *	* *
   ***   Programer: 陆晓春
    *    Date:		2004.05.20             */

CSymbolTable::CSymbolTable()
{
	initHashTable();
}

CSymbolTable::~CSymbolTable()
{
	for( int i = 0; i < SIZE; i++ ) if( hashTable[i] ) delete hashTable[i];
}

/*  *    CSymbolTable
    *    help routines
  *	* *
   ***   Programer: 陆晓春
    *    Date:		2004.05.20             */

// hash function
int CSymbolTable::hash( LPCTSTR key )
{
	int temp, i;

	for( temp = 0, i = 0; key[i] != '\0'; i++ )
		temp = ((temp << SHIFT) + key[i]) % SIZE;

	return temp;
}

void CSymbolTable::initHashTable()
{
	for( int i = 0; i < SIZE; i++ ) hashTable[i] = NULL;
}

void CSymbolTable::deleteHashTable()
{
	for( int i = 0; i < SIZE; i++ ) 
		if( hashTable[i] ) {
			delete hashTable[i];
			hashTable[i] = NULL;
		}
}

// write a string to m_file, m_file must exist
void CSymbolTable::write( char* format, ... )
{
	ASSERT( m_file.m_hFile != CFile::hFileNull );

	va_list params;
	static char buf[ 1024 ];
	
	va_start( params, format );
	_vsnprintf( buf, 1020, format, params );
	va_end( params );

	try {
		m_file.Write( buf, strlen(buf) );
	} catch( CFileException* ) {
		OutputErrMsg( "failed to write to file: %s", (LPCTSTR)m_file.GetFilePath() );
	}
}

/*  *    CSymbolTable
    *    public functions
  *	* *
   ***   Programer: 陆晓春
    *    Date:		2004.05.20             */

// insert a node into the hash table,
// memloc is inserted only the first time, otherwise ignored
void CSymbolTable::st_insert( CString& name, CString& scope, enum TokenType type,
							  int lineno, int memloc, BOOL bArray )
{
	int h = hash( (LPCTSTR)name );
	BucketListRec* l = hashTable[h];

	while( l && ((l->name != name) || (l->scope != scope)) ) l = l->next;
	if( l == NULL ) {
		// variable not yet in table
		l = new BucketListRec();
		l->name = name;
		l->scope = scope;
		l->type = type;
		l->memloc = memloc;
		l->bArray = bArray;
		l->lineno = new LineListRec();
		l->lineno->lineno = lineno;
		l->next = hashTable[h];
		hashTable[h] = l;
	} else {
		// found in table, so just add line number
		LineListRec* t = l->lineno;
		while( t->next ) t = t->next;
		t->next = new LineListRec();
		t->next->lineno = lineno;
	}
}

// lookup a node with specified name and scope from the hash table,
// return the memloc
int CSymbolTable::st_lookup( CString& name, CString& scope )
{
	int h = hash( (LPCTSTR)name );
	BucketListRec* l = hashTable[h];

	while( l && ((l->name != name) || (l->scope != scope)) ) l = l->next;
	return (l == NULL) ? -1 : l->memloc;
}

// check if it is array
BOOL CSymbolTable::st_lookup_isarray( CString& name, CString& scope )
{
	int h = hash( (LPCTSTR)name );
	BucketListRec* l = hashTable[h];

	while( l && ((l->name != name) || (l->scope != scope)) ) l = l->next;
	return (l == NULL) ? FALSE : l->bArray;
}

// return the type of the specified table node
enum TokenType CSymbolTable::st_lookup_type( CString& name, CString& scope )
{
	int h = hash( (LPCTSTR)name );
	BucketListRec* l = hashTable[h];

	while( l && ((l->name != name) || (l->scope != scope)) ) l = l->next;
	return (l == NULL ) ? _ERROR : l->type;
}

// print a formatted listing of the symbol table contents to lpszPathName
void CSymbolTable::PrintSymbolTable( LPCTSTR lpszPathName )
{
	// create file
	CFileException e;
	if( !m_file.Open( lpszPathName, CFile::modeCreate | CFile::modeReadWrite, &e ) ) {
		OutputErrMsg( "\r\nfailed to create file for printing symbol table: %s", lpszPathName );
		return;
	}

	write( "           Scope        Variable Name     Type     Location    Line Numbers\r\n" );
	write( "       -------------    -------------    ------    --------    ------------\r\n" );
	for( int i = 0; i < SIZE; i++ )
		if( hashTable[i] != NULL ) {
			BucketListRec* l = hashTable[i];
			while( l ) {
				write( "%18s", (LPCTSTR)l->scope );
				write( "%17s", (LPCTSTR)l->name );
				if( l->type == _LABEL )
					write( "%11s", "label" );
				else
					write( "%11s", (LPCTSTR)(ReservedKeywordList[l->type] + ((l->bArray) ? "[]" : "")) );
				write( "%12d     ", l->memloc );
				LineListRec* t = l->lineno;
				while( t ) {
					write( "%3d ", t->lineno );
					t = t->next;
				}
				write( "\r\n" );
				l = l->next;
			}
		}

		m_file.Close();
}